/*
 * Copyright (C) 2015-2017 Alibaba Group Holding Limited
 */

#include <stddef.h>
#include <stdio.h>
#include <string.h>
#include <stdbool.h>
#include <aos/kernel.h>
#include <aos/hal/flash.h>
#include "board_partitions.h"

/* Logic partition on flash devices */
const hal_logic_partition_t hal_partitions[] =
{
    [HAL_PARTITION_BOOTLOADER] =
    {
        .partition_owner            = HAL_FLASH_QSPI,
        .partition_description      = "Bootloader",
        .partition_start_addr       = BOOTLOADER_PARTITION_START,
        .partition_length           = BOOTLOADER_PARTITION_SIZE,    
        .partition_options          = PAR_OPT_READ_EN | PAR_OPT_WRITE_DIS,
    },
    [HAL_PARTITION_CUSTOM_1] =
    {
        .partition_owner            = HAL_FLASH_QSPI,
        .partition_description      = "Boot para",
        .partition_start_addr       = BOOTLOADER_PARAM_PARTITION_START,
        .partition_length           = BOOTLOADER_PARAM_PARTITION_SIZE,  
        .partition_options          = PAR_OPT_READ_EN | PAR_OPT_WRITE_EN,
    },
    [HAL_PARTITION_APPLICATION] =
    {
        .partition_owner            = HAL_FLASH_QSPI,
        .partition_description      = "Application",
        .partition_start_addr       = APPLICATION_PARTITION_START,
        .partition_length           = APPLICATION_PARTITION_SIZE,  
        .partition_options          = PAR_OPT_READ_EN | PAR_OPT_WRITE_EN,
    },
    [HAL_PARTITION_PARAMETER_2] =
    {
        .partition_owner            = HAL_FLASH_QSPI,
        .partition_description      = "Key Value",
        .partition_start_addr       = KV_PARTITION_START,
        .partition_length           = KV_PARTITION_SIZE,  
        .partition_options          = PAR_OPT_READ_EN | PAR_OPT_WRITE_EN,
    },
    [HAL_PARTITION_SPIFFS] = 		
	{
		.partition_owner			= HAL_FLASH_QSPI,
		.partition_description		= "fatfs",
		.partition_start_addr		= FS_PARTITION_START,
		.partition_length			= FS_PARTITION_SIZE,  
		.partition_options			= PAR_OPT_READ_EN | PAR_OPT_WRITE_EN,
	},
#if 0
    [HAL_PARTITION_CUSTOM_1] =
    {
        .partition_owner            = HAL_FLASH_QSPI,
        .partition_description      = "user data",
        .partition_start_addr       = CUSTOM_PARTITION_START,
        .partition_length           = CUSTOM_PARTITION_SIZE,  
        .partition_options          = PAR_OPT_READ_EN | PAR_OPT_WRITE_EN,
    },
#endif
};

hal_logic_partition_t* board_get_info(hal_partition_t in_partition)
{
    hal_logic_partition_t *logic_partition;

    logic_partition = (hal_logic_partition_t *)&hal_partitions[ in_partition ];

    return logic_partition;
}

static int partition(hal_logic_partition_t arr[], int left, int right) {
    int i = left + 1;
    int j = right;
    hal_logic_partition_t pivot = arr[left];
    while (true) {
        while (i <= j && arr[i].partition_start_addr <= pivot.partition_start_addr) i++;
        while(i <= j && arr[j].partition_start_addr >= pivot.partition_start_addr ) j--;
        if(i >= j)
            break;
        hal_logic_partition_t temp = arr[i];
        arr[i] = arr[j];
        arr[j] = temp;
    }
    arr[left] = arr[j];
    arr[j] = pivot;
    return j;
}

static hal_logic_partition_t *quickSort(hal_logic_partition_t arr[], int left, int right) {
    if (left < right) {
        int mid = partition(arr, left, right);
        arr = quickSort(arr, left, mid - 1);
        arr = quickSort(arr, mid + 1, right);
    }
    return arr;
}

int print_partiton_table(void)
{
    uint8_t part_cnt = 0;
    hal_logic_partition_t *part_orderd = NULL;

    printf("\n\n*************************FLASH PARTITION TABLE***************************\n");
    printf("\t%-20s%-20s%-20s\n", "Part Name", "Start Addr", "Part Length");      

    for(int part = HAL_PARTITION_BOOTLOADER; part < HAL_PARTITION_MAX; part++) {
        hal_logic_partition_t *part_info = board_get_info(part);
        if(part_info->partition_description == NULL) 
            continue;
        part_cnt++;    
    }
    
    part_orderd = (hal_logic_partition_t *)aos_zalloc(part_cnt * sizeof(hal_logic_partition_t));
    if (NULL == part_orderd) {
        printf("zalloc error!\n");
        return -1;
    }
    for(int part = HAL_PARTITION_BOOTLOADER, i = 0; part < HAL_PARTITION_MAX && i < part_cnt; part++) {
        hal_logic_partition_t *part_info = board_get_info(part);
        if(part_info->partition_description == NULL) 
            continue;
        memcpy((uint8_t*)&part_orderd[i], (uint8_t*)part_info, sizeof(hal_logic_partition_t));    
        i++;
    }
    quickSort(part_orderd, 0, part_cnt - 1);
    for(int part = 0; part < part_cnt; part++) {
        printf("\t%-20s0x%-18llx0x%-18llx\n", part_orderd[part].partition_description, (long long)part_orderd[part].partition_start_addr,
            (long long)part_orderd[part].partition_length);
    }
    aos_free(part_orderd);
    printf("\n*************************************************************************\n");

    return 0;
}


